import { PBRShader } from "./js/shaders.js";
const canvas = document.getElementById("renderCanvas"); // Get the canvas element
let shadowGenerator;
let light;
// 尝试获取 WebGL2 上下文
const gl = canvas.getContext("webgl2");
if (gl) {
  console.log("支持 WebGL 2.0");
} else {
  alert("设备不支持 WebGL 2.0");
}
// const vertexBuffer = new BABYLON.VertexBuffer()
const engine = new BABYLON.Engine(canvas, true, {
  antialias: true, // 开启抗锯齿
}); // Generate the BABYLON 3D engine
function showWorldAxis(size, scene) {
  const makeAxis = function (axis, color) {
    const axisMaterial = new BABYLON.StandardMaterial("axisMat", scene);
    axisMaterial.diffuseColor = color;
    axisMaterial.emissiveColor = color;

    const axisLine = BABYLON.MeshBuilder.CreateLines(
      "axis" + axis,
      {
        points: [
          BABYLON.Vector3.Zero(),
          axis === "X"
            ? new BABYLON.Vector3(size, 0, 0)
            : axis === "Y"
            ? new BABYLON.Vector3(0, size, 0)
            : new BABYLON.Vector3(0, 0, size),
        ],
      },
      scene
    );
    axisLine.color = color;
  };

  makeAxis("X", BABYLON.Color3.Red()); // 红色X轴
  makeAxis("Y", BABYLON.Color3.Green()); // 绿色Y轴
  makeAxis("Z", BABYLON.Color3.Blue()); // 蓝色Z轴
}
const createScene = function () {
  // Creates a basic Babylon Scene object
  const scene = new BABYLON.Scene(engine);
  scene.gravity = new BABYLON.Vector3(0, -0.15, 0); // 设置相机重力
  /** 普通观察相机 */
  // const camera = new BABYLON.ArcRotateCamera(
  //   "camera",
  //   -Math.PI / 2,
  //   Math.PI / 2.5,
  //   3,
  //   new BABYLON.Vector3(0, 0, 0),
  //   scene
  // );
  // // camera.upperBetaLimit = Math.PI / 2.1;    // 限制相机上下旋转角度
  // // Targets the camera to scene origin
  // camera.setTarget(BABYLON.Vector3.Zero());
  // // This attaches the camera to the canvas
  // camera.attachControl(canvas, true);

  /** 第一人称相机  */
  const camera = new BABYLON.UniversalCamera(
    "FPSCamera",
    new BABYLON.Vector3(0, 1, 0),
    scene
  );
  camera.attachControl(canvas, true);
  // 设置 WASD 键位控制
  camera.keysUp.push(87); // W
  camera.keysDown.push(83); // S
  camera.keysLeft.push(65); // A
  camera.keysRight.push(68); // D

  // 设置相机参数
  camera.speed = 1;
  camera.angularSensibility = 500; // 鼠标灵敏度
  camera.inertia = 0; // 视角拖尾关闭
  /** 虚拟摇杆相机 */
  //   const camera = new BABYLON.VirtualJoysticksCamera(
  //     "VJC",
  //     new BABYLON.Vector3(0, 1.5, 0),
  //     scene
  //   );

  //   // Attach camera to canvas inputs
  //   camera.attachControl(canvas);

  camera.applyGravity = true; // 开启重力
  camera.checkCollisions = true; // 开启碰撞检测
  scene.activeCamera = camera;

  	// Creates the post process
	// var postProcess = new BABYLON.DigitalRainPostProcess("DigitalRain", camera);
  showWorldAxis(5, scene); // 显示坐标轴
  // 环境光
  // const ambientLight = new BABYLON.HemisphericLight(
  //   "light",
  //   new BABYLON.Vector3(0, 1, 0),
  //   scene
  // );
  // ambientLight.intensity = 0.2;
  // 平行光
  light = new BABYLON.DirectionalLight(
    "light",
    new BABYLON.Vector3(0, -1, 0),
    scene
  );
  light.intensity = 1.0;
  light.autoCalcShadowZBounds = true;
  // Dim the light a small amount - 0 to 1
  // light.autoCalcShadowZBounds = true;
  // shadowGenerator = new BABYLON.CascadedShadowGenerator(512, light); // 创建级联阴影生成器
  // shadowGenerator.numCascades = 2; // 阶梯数量
  // shadowGenerator.lambda = 0.5; // 阴影分割权重
  // shadowGenerator.shadowMaxZ = 20;
  // shadowGenerator.shadowMinZ = 0.1;
  // // shadowGenerator.stabilizeCascades = true;
  // shadowGenerator.filteringQuality = BABYLON.ShadowGenerator.QUALITY_LOW;
  // shadowGenerator.filter = BABYLON.ShadowGenerator.FILTER_PCF; // PCF软阴影

  const floor = BABYLON.MeshBuilder.CreateGround("ground", {
    width: 100,
    height: 100,
  });
  floor.position.y = -0.1;
  floor.checkCollisions = true;
  // floor.receiveShadows = true;
  return scene;
};

// 自定义加载界面类
class MyLoadingScreen {
  constructor(text) {
    this.progress = 0;
    this.text = text;
    this.loadingUIText = `${this.progress}%,${text}`;
    this.loadingDiv = document.createElement("div");
    this.loadingDiv.style.backgroundColor = "white";
    this.loadingDiv.style.width = "100%";
    this.loadingDiv.style.height = "100%";
    this.loadingDiv.style.display = "flex";
    this.loadingDiv.style.alignItems = "center";
    this.loadingDiv.style.justifyContent = "center";
    this.loadingDiv.id = "loadingScreen";
    this.loadingDiv.style.position = "absolute";
    this.loadingDiv.style.top = "0%";
    this.loadingDiv.style.left = "0%";
    // this.loadingDiv.style.transform = "translate(-50%, -50%)";
    this.loadingDiv.style.zIndex = "1000";
    this.loadingDiv.style.color = "white";
    this.loadingDiv.style.fontFamily = "Arial";
  }
  updateLoadingUI(progress) {
    this.progress = progress;
    this.loadingUIText = `${this.progress}%,${this.text}`;
    this.loadingDiv.innerHTML =
      "<h1 style='color:black;'>" + this.loadingUIText + "</h1>";
  }
  displayLoadingUI() {
    document.body.appendChild(this.loadingDiv);
  }

  hideLoadingUI() {
    if (this.loadingDiv.parentNode) {
      this.loadingDiv.parentNode.removeChild(this.loadingDiv);
    }
  }
}
// 设置gui
const setGUI = async (scene, callback) => {
  // 创建 GUI 层
  const adt = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
  const panel = new BABYLON.GUI.StackPanel();
  panel.width = "220px";
  panel.top = "-25px";
  panel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;
  panel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_BOTTOM;
  adt.addControl(panel);
  // 创建标题
  const header = new BABYLON.GUI.TextBlock();
  header.text = "Night to Day";
  header.height = "30px";
  header.color = "white";
  panel.addControl(header);

  // 创建滑动条
  const slider = new BABYLON.GUI.Slider();
  slider.minimum = 0;
  slider.maximum = 100;
  slider.value = 50;
  slider.width = "200px";
  slider.height = "20px";
  slider.color = "orange";

  slider.onValueChangedObservable.add((value) => {
    callback(value);
    console.log("滑动条数值：", value);
    // 根据 value 控制某些参数
  });
  panel.addControl(slider);
};
// 加载模型
const loadModel = async function (scene, onProgress) {
  //   BABYLON.SceneLoader.ImportMesh(
  //     "", // "" for all
  //     "/models/",
  //     "scene_1.gltf",
  //     scene,
  //     onSuccess,
  //     onProgress,
  //     onError
  //   );
  let result = await BABYLON.ImportMeshAsync("./models/scene_1.gltf", scene, {
    meshNames: "",
    onProgress,
  });
  console.log("result", result);
  let materials = [];
  result.meshes.map((mesh, index) => {
    if (index == 0) return;
    // result.meshes[index].position = new BABYLON.Vector3(0,100,0);
    // result.meshes[index].scaling = new BABYLON.Vector3(10,10,10);
    // shadowGenerator.addShadowCaster(mesh); // 投射阴影

    // 使用自定义shader
    let pbrmat = mesh.material;
    // mesh.scaling = new BABYLON.Vector3(10,10,10);
    // mesh.position.y = 100
    if (pbrmat) {
      const customMaterial = PBRShader(scene, index);
      // 传递 贴图
      if (pbrmat.albedoTexture) {
        customMaterial.setTexture("albedoTexture", pbrmat.albedoTexture); // 基本颜色
      }
      if (pbrmat.bumpTexture) {
        customMaterial.setTexture("normalTexture", pbrmat.bumpTexture); // 法线贴图
      }
      if (pbrmat.metallicTexture) {
        customMaterial.setTexture(
          "metallicRoughnessTexture",
          pbrmat.metallicTexture
        ); // 金属度和粗糙度贴图
      }
      if (
        pbrmat.albedoTexture &&
        pbrmat.bumpTexture &&
        pbrmat.metallicTexture
      ) {
        mesh.material = customMaterial;
        materials.push(customMaterial);
      }
    }
  });
  setGUI(scene, (value) => {
    const u = ((value / 100) * 2 - 1) * Math.PI;
    let angle = new BABYLON.Vector3(0, Math.cos(u), Math.sin(u)); // 设置光源位置
    let scaleangle = angle.scale(100);
    light.direction = new BABYLON.Vector3(
      0,
      -1 * Math.cos(u),
      -1 * Math.sin(u)
    ).normalize();
    console.log("light.direction", light.direction);
    materials.map((mat) => {
      mat.setVector3("uLightWorldPos", scaleangle);
    });
  });
  return result;
};
// 设置自定义加载界面
const loadingScreen = new MyLoadingScreen("正在加载模型，请稍候...");
engine.loadingScreen = loadingScreen;
const scene = await createScene(); //Call the createScene function
// 显示加载界面
engine.displayLoadingUI();
await loadModel(scene, (e) => {
  // console.log(e);
  let progress = ((e.loaded / e.total) * 100).toFixed(2);
  loadingScreen.updateLoadingUI(progress);
});
// 模型加载完成后隐藏加载界面
engine.hideLoadingUI();

// Register a render loop to repeatedly render the scene
engine.runRenderLoop(function () {
  scene.render();
});
// Watch for browser/canvas resize events
window.addEventListener("resize", function () {
  engine.resize();
});
